/**
 * 月内 摘挂牌
 */

import { yunNao } from "@src/api/yunNao"
import { requestSDspotMarketZcq } from "@src/api/fetch"
import { getSpotMartetZcqReqInfo } from "@src/entries/options/generate"
import { getPrivateCommonParams } from "@src/spotMarketPrivateData/data"
import dayjs from "dayjs"
import { PDetailForm, PDetailTable, SellerBuyerPublic } from "./type"
import { AsyncRecursion, CbParams, creatAsyncRecursion } from '@src/utils/asyncRecursion'
import { promisetTimeOut } from "@src/utils/common"
import { throttle } from 'lodash'
import { handleState } from "@src/entries/background/spotMarketZcqReq"
import { priviateAccount, userUnitid } from "@src/config/accountInfo"

/** 所有请求成功过的详情 */
let alreadyGetDetailList:number[] = []
/** 在交易时段时 每一轮供需数据的间隔时间 */
const zgpTradingTimer = 1000 * 30
/** 非交易时段时 每一轮供需数据的间隔时间 */
const zgpMuteTimer = 1000 * 110
/** 记录供需timer */
const allBuyTimeOutTimerList:Array<ReturnType<typeof setTimeout>> = []
const allSellTimeOutTimerList:Array<ReturnType<typeof setTimeout>> = []
/** 清除所有供需 timeOut */
const clearAllSellTimeOut = () => {
  allSellTimeOutTimerList.forEach(val => clearTimeout(val))
  allSellTimeOutTimerList.length = 0
}
const clearAllBuyTimeOut = () => {
  allBuyTimeOutTimerList.forEach(val => clearTimeout(val))
  allBuyTimeOutTimerList.length = 0
}

/** 记录timer */
const allTimeOutTimerList:Array<ReturnType<typeof setTimeout>> = []
/** 清除所有 timeOut */
const clearAllTimeOut = () => {
  allTimeOutTimerList.forEach(val => clearTimeout(val))
  allTimeOutTimerList.length = 0

  clearAllSellTimeOut()
  clearAllBuyTimeOut()
}

// let handleState = true
let sceneList:any[] = []
let handleTradeDay = ''
let the_kpid_jydm = ''
let handleDataType:'月度挂牌交易'|'日挂牌交易'
let theDateSceneIndx = 0 //当天的交易场次序号
export const setHandleTradeDay = (date:string, type:'月度挂牌交易'|'日挂牌交易' = '月度挂牌交易', index = 0) => {
  theDateSceneIndx = index
  the_kpid_jydm = ''
  alreadyGetDetailList = []
  handleDataType = type
  handleTradeDay = dayjs(date).format('YYYY-MM-DD')
}

const isZhaiGuaPaiTrade = () => {
  if(!sceneList?.length) {
    console.error('无交易场次列表')
    getAllZGBTradePlantDetail()
    return false
  }
  if(handleState) {
    const tradePlantList = sceneList.filter(item => item.jysbsjks.includes(handleTradeDay) && item.content.includes(handleDataType))
    const tradePlant = tradePlantList[theDateSceneIndx]
    if(!tradePlant) {
      console.error(`找不到${handleTradeDay}交易场次`)
      return false
    }
    const {kpid_jydm} = tradePlant
    the_kpid_jydm = kpid_jydm
    return true
  }
  const sbDate = dayjs().format('YYYY-MM-DD')
  const tradePlantList = sceneList.filter(item => item.jysbsjks.includes(sbDate))
  if(!tradePlantList?.length) return false
  const offsetTime = 3 * 60 * 1000
  return tradePlantList.some(item => {
    const {jysbsjks,jysbsjjs,kpid_jydm} = item
    const nowNum = dayjs().valueOf()
    const getDataStartEnd = [dayjs(jysbsjks).valueOf() - offsetTime, dayjs(jysbsjjs).valueOf() + offsetTime]
    const isGet = nowNum > getDataStartEnd[0] && nowNum < getDataStartEnd[1]
    if(isGet) the_kpid_jydm = kpid_jydm
    return isGet
  })
}

// const getTradePlanList = async ({headers,monthsList}:{headers:HeadersInit, monthsList:string[]}) => {
//   try {
//     const htmlStr:string = await requestSDspotMarketZcq(
//       `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?appkey=127`,
//       undefined,
//       { method:'GET', headers },
//       'text'
//     )

//     const kpid_jydmDataList = (htmlStr.match(/<option\b[^>]*>[\s\S]*?<\/option>/gi) || []).filter(val => /^(?=.*(月度挂牌交易|日挂牌交易))(?!.*测试).*$/.test(val)).map(item => {
//       const regex = /<option[^>]*value=["']([^"']+)["'][^>]*>(.*?)<\/option>/;
//       const match = item.match(regex);
//       return {
//         kpid_jydm:match ? match[1] : '',
//         content:match ? match[2] : '',
//       }
//     }).filter(val => monthsList.some(value => (val?.content || '').includes(value)))

//     return Promise.resolve(kpid_jydmDataList)
//   }catch(e) {
//     console.error(e)
//     return Promise.reject(e)
//   }
// }

const getTradePlanList = async ({headers,monthsList}:{headers:HeadersInit, monthsList:string[]}) => {
  try {
    const formParams = new URLSearchParams({
      startDate: monthsList[0],
      endDate: monthsList[1]
    })

    const sceneObj = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=getKpxx`,
      formParams,
      { method:'POST', headers },
    )

    const kpid_jydmDataList:Array<{kpid_jydm: string,content: string}> = (sceneObj?.kpxxlist || []).filter((item:any) => /^(?=.*(月度挂牌交易|日挂牌交易))(?!.*测).*$/.test(item.kpmc)).map((val:any) => ({
      kpid_jydm: `${val.kpid}_${val.jydm}`,
      content: val.kpmc,
    }))

    // const kpid_jydmDataList = (htmlStr.match(/<option\b[^>]*>[\s\S]*?<\/option>/gi) || []).filter(val => /^(?=.*(月度挂牌交易|日挂牌交易))(?!.*测试).*$/.test(val)).map(item => {
    //   const regex = /<option[^>]*value=["']([^"']+)["'][^>]*>(.*?)<\/option>/;
    //   const match = item.match(regex);
    //   return {
    //     kpid_jydm:match ? match[1] : '',
    //     content:match ? match[2] : '',
    //   }
    // }).filter(val => monthsList.some(value => (val?.content || '').includes(value)))

    return Promise.resolve(kpid_jydmDataList)
  }catch(e) {
    console.error(e)
    return Promise.reject(e)
  }
}

const getOneTradePlanDetail = async ({kpid_jydm,content, headers}:{kpid_jydm:string,content:string,headers:HeadersInit}) => {
  try {
  //   {
  //     "jysbsj": "2024-11-21 09:00~2024-11-21 10:00",
  //     "jgsx": 1300.0000,
  //     "jgxx": -80.0000,
  //     "maxjgFs": 1300.0000,
  //     "minjgFs": -80.0000,
  //     "gpjssj": "2024-11-21 09:50",
  //     "bdkssj": "2024-11-25",
  //     "bdjssj": "2024-11-30",
  //     "sfyyfsdj": "1",
  //     "sfzfsqhy": "0",
  //     "showXyjc": "0"
  // }
    const dataObj = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=getYsxx&kpid_jydm=${kpid_jydm}&jydyid=${userUnitid[priviateAccount]}`,
      undefined,
      { method:'POST', headers }
    )

    const formatStr = 'YYYY-MM-DD HH:mm:ss'
    const {
      jysbsj = '',
      bdkssj = '',
      bdjssj = '',
      gpjssj = '',
    } = dataObj || {}

    const [jysbsjks = '', jysbsjjs = ''] = jysbsj.split('~')

    let sceneType:null|number = null

    if(content.includes('日挂牌交易')) sceneType = 1
    if(content.includes('月度挂牌交易')) sceneType = 2

    const dealedData = {
      "bdjssj": dayjs(bdjssj).format(formatStr),// "申报结束时间,类型：string",
      "bdkssj": dayjs(bdkssj).format(formatStr),// "申报开始时间,类型：string",
      "delisteEndTime": dayjs(gpjssj).format(formatStr),// "挂牌结束时间,类型：string",
      "jysbsjjs": dayjs(jysbsjjs).format(formatStr), // "交易标的结束日期,类型：string",
      "jysbsjks": dayjs(jysbsjks).format(formatStr), // "交易标的开始日期,类型：string",
      kpid_jydm, // "交易中心场次id,类型：string",
      sceneType, // "场次类型，1-挂摘牌（月内挂牌）2-挂摘牌（月度挂牌）,类型：integer"
      content
    }

    return Promise.resolve(dealedData)

  }catch(e) {
    console.error(e)
  }
}

/**
 * 获取交易场次列表
 * 启动时更新一次，一天更新两次
 * @param param0
 */
export const getAllZGBTradePlantDetail = async (headers?:HeadersInit, theMonth = dayjs().format('YYYY-MM')) => {
  console.log('getAllZGBTradePlantDetail')
  try {
    if(!headers) {
      const reqInfo = await getSpotMartetZcqReqInfo()
      headers = reqInfo.headers
    }

    const monthsList = [dayjs(theMonth).subtract(1,'month').startOf('month').format('YYYY-MM-DD'), dayjs(theMonth).add(1,'month').endOf('month').format('YYYY-MM-DD')]
    const kpid_jydmDataList = await getTradePlanList({headers, monthsList})

    const reqParamsList = kpid_jydmDataList.map(item => ({...item, headers}))

    const allNodeData:CbParams = await creatAsyncRecursion(AsyncRecursion, {
      stepAsyncFnParamsList: reqParamsList,
      stepAsyncFn: getOneTradePlanDetail,
      stepCb: async () => await promisetTimeOut(100), 
      stepAsyncNum: 1,
      errBreak: false
    }).start()

    sceneList = (allNodeData?.allResultList || []).flat()

    const saveDataList = {
      ...getPrivateCommonParams({thirdId:userUnitid[priviateAccount]}),
      itemCode:'save_medium_trade_scene',
      sceneList
    }

    console.log('存储数据：getAllTradePlantDetail', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("爬取数据存储成功 getAllTradePlantDetail", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  }
}

/** 买卖牌详情1 form表单内相关数据*/
export const getOneGpxxData= async ({headers, gpid}:{headers:HeadersInit,gpid:number|string}) => {
  try {
    const formParams = new URLSearchParams({
      gpid:String(gpid)
    })
  
    const dataObj:PDetailForm = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=getGpxxData`,
      formParams,
      { method:'POST', headers }
    )
    console.log('getOneGpxxData')
    return Promise.resolve(dataObj)
  }catch(e) {
    console.error(e)
    return Promise.reject(e)
  }
}

/** 买卖牌详情2 表格内数据*/
const queryOnedatabale = async ({headers, gpid}:{headers:HeadersInit,gpid:number}) => {
  try {
    const formParams = new URLSearchParams({
      cjid: String(gpid)
    })
  
    const dataObj = await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=querydatabale`,
      formParams,
      { method:'POST', headers }
    )
    console.log('queryOnedatabale')
    let data:PDetailTable[] = dataObj?.data || []
    // if(data.length) {
    //   data = JSON.parse(JSON.stringify(data).replace(/\"-\"/g,'\"\"'))
    // }
    return Promise.resolve(data)
  }catch(e) {
    console.error(e)
    return Promise.reject(e)
  }
}

/** 买卖 单个的牌详情 form内和表格内数据 */
const getOneDetail = async ({headers, gpid}:{headers:HeadersInit,gpid:number}) => {
  try {
    const [detailForm, detailTable] = await Promise.allSettled([getOneGpxxData({headers,gpid}),queryOnedatabale({headers,gpid})])
    
    const {gpdj = '', gpdl = '', jyjssj = '', jykssj = ''} = detailForm.status === 'fulfilled' ? detailForm.value : {}
    const saveData = {
      gpid,
      gpdj,gpdl,jyjssj,jykssj,
      detailTable: detailTable.status === 'fulfilled' ? detailTable.value : []
    }

    // 单个详情请求成功
    if(detailForm.status === 'fulfilled' && detailTable.status === 'fulfilled') {
      alreadyGetDetailList.push(gpid)
    }

    return Promise.resolve(saveData)
  }catch(e) {
    console.error(e)
    return Promise.reject(e)
  }
}

/** 买卖方挂牌信息列表及详情 */
const getSaveBuyerOrSellerPublicListAndDetail = async ({headers, unitid, type}:{headers:HeadersInit,unitid:string, type:'buy' | 'sell'}) => {
  console.log('getSaveBuyerOrSellerPublicListAndDetail 买卖方挂牌信息列表及详情', dayjs().format('YYYY-MM-DD HH:mm:ss'))
  let zgpTimeReal = zgpTradingTimer
  try {
    if(type === 'buy') {
      clearAllBuyTimeOut()
    }else {
      clearAllSellTimeOut()
    }

    if(!isZhaiGuaPaiTrade()) {
      the_kpid_jydm = ''
      alreadyGetDetailList = []
      zgpTimeReal = zgpMuteTimer
      return Promise.resolve()
    }

    zgpTimeReal = zgpTradingTimer

    if(!the_kpid_jydm) {
      console.log('获取the_kpid_jydm失败')
      return Promise.resolve()
    }
    const kpid_jydm = the_kpid_jydm

    const dataTypes = {
      buy: {
        method: 'getAllBuyData',
        tradeType: 1
      },
      sell:{
        method: 'getAllSellData',
        tradeType: 2
      }
    }

    const {method, tradeType} = dataTypes[type]

    const publicObj= await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=${method}&kpid_jydm=${kpid_jydm}&_=${new Date().getTime()}`,
      undefined,
      { method:'GET', headers }
    )

    const publicList:SellerBuyerPublic[] = (publicObj?.data || []).map((item:SellerBuyerPublic) => {
      const [targetStartDate = '', targetEndDate = ''] = (item?.hybdsj || '').split('~')
      item.targetStartDate = dayjs(targetStartDate).format('YYYY-MM-DD HH:mm:ss')
      item.targetEndDate = dayjs(targetEndDate).format('YYYY-MM-DD HH:mm:ss')

      item.tradeType = tradeType as 1 | 2
      item.tradeDate = handleState && kpid_jydm ? dayjs(handleTradeDay).format('YYYY-MM-DD') : dayjs().format('YYYY-MM-DD')
      item.kpid_jydm = kpid_jydm || ''
      return item
    })

    const toGetDetailList = publicList.filter(item => !alreadyGetDetailList.includes(item.gpid))
    const reqParamsList = toGetDetailList.map(item => ({gpid:item.gpid, headers}))

    const allNodeData:CbParams = await creatAsyncRecursion(AsyncRecursion, {
      stepAsyncFnParamsList: reqParamsList,
      stepAsyncFn: getOneDetail,
      stepCb: async () => await promisetTimeOut(100), 
      stepAsyncNum: 1,
      errBreak: false
    }).start()

    const saveDataList = {
      ...getPrivateCommonParams({thirdId:unitid}),
      itemCode:'delist_trade_contract_data',
      kpid_jydm,
      publicList,
      publicDetailList: (allNodeData?.allResultList || []).flat()
    }
    
    console.log('存储数据：getSaveBuyerOrSellerPublicListAndDetail', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("获取数据存储成功 getSaveBuyerOrSellerPublicListAndDetail", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  }finally {
    if(handleState) return

    if(type === 'buy') {
      clearAllBuyTimeOut()
      const buyTimer = setTimeout(() => getSaveBuyerOrSellerPublicListAndDetail({headers, unitid, type}), zgpTimeReal)
      allBuyTimeOutTimerList.push(buyTimer)
    }else {
      clearAllSellTimeOut()
      const sellTimer = setTimeout(() => getSaveBuyerOrSellerPublicListAndDetail({headers, unitid, type}), zgpTimeReal)
      allSellTimeOutTimerList.push(sellTimer)
    }
  }
}

/** (公有) 买方挂牌信息列表 */
export const getSaveBuyerPublicListAndDetailThrottle = throttle(getSaveBuyerOrSellerPublicListAndDetail, 2000, {trailing:true, leading: false})
/** (公有) 卖方挂牌信息列表 */
export const getSaveSellerPublicListAndDetailThrottle = throttle(getSaveBuyerOrSellerPublicListAndDetail, 2000, {trailing:true, leading: false})


/** 记录供需timer */
const allMyZTimeOutTimerList:Array<ReturnType<typeof setTimeout>> = []
const allMyGTimeOutTimerList:Array<ReturnType<typeof setTimeout>> = []
/** 清除所有供需 timeOut */
const clearAllMyGTimeOut = () => {
  allMyGTimeOutTimerList.forEach(val => clearTimeout(val))
  allMyGTimeOutTimerList.length = 0
}
const clearAllMyZTimeOut = () => {
  allMyZTimeOutTimerList.forEach(val => clearTimeout(val))
  allMyZTimeOutTimerList.length = 0
}

/** 我的摘挂牌信息列表 */
const getSaveZGPMyListAndDetail = async ({headers, unitid, type}:{headers:HeadersInit,unitid:string, type:'zhai' | 'gua'}) => {
  console.log('getSaveZGPMyListAndDetail 我的摘挂牌信息列表', dayjs().format('YYYY-MM-DD HH:mm:ss'))
  let zgpTimeReal = zgpTradingTimer
  try {
    if(type === 'zhai') {
      clearAllMyZTimeOut()
    }else {
      clearAllMyGTimeOut()
    }

    if(!isZhaiGuaPaiTrade()) {
      the_kpid_jydm = ''
      zgpTimeReal = zgpMuteTimer
      return Promise.resolve()
    }

    zgpTimeReal = zgpTradingTimer

    if(!the_kpid_jydm) {
      console.log('获取the_kpid_jydm失败')
      return Promise.resolve()
    }
    const kpid_jydm = the_kpid_jydm

    const dataTypes = {
      zhai: {
        method: 'getMyZpData',
        itemCode: 'xxxxxxxxxxxxxgetMyZpData'
      },
      gua:{
        method: 'getMyGpData',
        itemCode: 'xxxxxxxxxxxxxgetMyGpData'
      }
    }

    const {method, itemCode} = dataTypes[type]

    const publicObj= await requestSDspotMarketZcq(
      `https://pmos.sd.sgcc.com.cn:18080/zcq/scgpjy/jysb.do?method=${method}&kpid_jydm=${kpid_jydm}&jydyid=${unitid}`,
      undefined,
      { method:'POST', headers }
    )

    const publicList:SellerBuyerPublic[] = publicObj?.data || []

    const saveDataList = {
      ...getPrivateCommonParams({thirdId:unitid}),
      itemCode,
      publicList
    }
    
    console.log('存储数据：getSaveZGPMyListAndDetail', saveDataList)
    await yunNao.saveJson(saveDataList)
    console.log("爬取数据存储成功 getSaveZGPMyListAndDetail", dayjs().format("YYYY-MM-DD HH:mm:ss"))
  }catch(e) {
    console.error(e)
  }finally {
    if(type === 'zhai') {
      clearAllMyZTimeOut()
      const buyTimer = setTimeout(() => getSaveZGPMyListAndDetail({headers, unitid, type}), zgpTimeReal)
      allMyZTimeOutTimerList.push(buyTimer)
    }else {
      clearAllMyGTimeOut()
      const sellTimer = setTimeout(() => getSaveZGPMyListAndDetail({headers, unitid, type}), zgpTimeReal)
      allMyGTimeOutTimerList.push(sellTimer)
    }
  }
}

/** (私有) 我的摘牌信息列表 */
export const getSaveZPMyListAndDetailThrottle = throttle(getSaveZGPMyListAndDetail, 2000, {trailing:true, leading: false})

// /** (私有) 我的挂牌信息列表 */
// export const getSaveGPMyListAndDetailThrottle = throttle(getSaveZGPMyListAndDetail, 2000, {trailing:true, leading: false})


// const intervalSeconds = 30
// /** 创建所有类型对应的所有的请求 的  请求间隔*/
// const createAllIntervalReq = ({headers, unitid}:{headers:HeadersInit,unitid:string}) => {
//   console.log(
//     `%c 创建滚动撮合getRollData，每${intervalSeconds}秒执行一次`,
//     'background:#35495e ; padding: 1px; border-radius: 3px 0 0 3px;  color: #fff',
//   )

//   clearAllTimeOut()

//   const timeOutTimer = setTimeout(() => {
//     // getRollData({headers, unitid})
//     createAllIntervalReq({headers,unitid})
//   }, intervalSeconds * 1000)
  
//   // getRollData({headers, unitid})

//   allTimeOutTimerList.push(timeOutTimer)
// }

//  /** 创建所有类型的所有接口的定时请求 */
//  const createZGPDataLoop = ({headers, unitid}:{headers:HeadersInit,unitid:string}) => {
//    the_kpid_jydm = ''

//   //  getRollData({headers, unitid})
//   //  createAllIntervalReq({headers,unitid})

//   getSaveBuyerOrSellerPublicListAndDetailThrottle({headers,unitid, type:'buy'})
//   getSaveBuyerOrSellerPublicListAndDetailThrottle({headers,unitid, type:'sell'})
//  }

// /** 唯一出口函数 */
// export const createZGPDataLoopThrottle = throttle(createZGPDataLoop, 5000, {trailing:true, leading: false})